import L from "leaflet"

L.tycircleLayer = L.Layer.extend({
    includes: L.Mixin.Events,
    options: {
        lineWidth: 2,
        scale: 1,
        zIndex: 15,
        allData: [],
        strokeStyle: "rgba(0,139,139,0.6)",//no
        fillStyle: "rgba(0,205,205,0.2)",//no
        allowDraw: true,//no
        showLabel: true,//no
        opacity: 1,//no
        weight: 0.8,//no
    },
    initialize: function (options) {
        L.setOptions(this, options)
    },
    onAdd: function (map) {
        this._map = map
        if (!this._container) { this._initCanvas() }
        map._panes.overlayPane.appendChild(this._container)
        map.on('zoomstart', this._clearcanvas, this)
        map.on('moveend', this._reset, this)
        if (map.options.zoomAnimation && L.Browser.any3d) {
            map.on('zoomanim', this._animateZoom, this)
        }
    },
    onRemove: function (map) {
        map.getPanes().overlayPane.removeChild(this._container)
        map.off('zoomstart', this._clearcanvas, this)
        map.off('moveend', this._reset, this)
        if (map.options.zoomAnimation) {
            map.off('zoomanim', this._animateZoom, this)
        }
    },
    addTo: function (map) {
        map.addLayer(this)
        return this
    },
    bringToBack: function () {
        let pane = this._map._panes.overlayPane
        if (this._canvas) {
            pane.insertBefore(this._canvas, pane.firstChild)
        }
        return this
    },
    _setZindex: function (Zindex) {
        this._container.style.zIndex = Zindex
    },
    _initCanvas: function () {
        this._container = L.DomUtil.create('div', 'leaflet-image-layer')
        this._canvas = L.DomUtil.create('canvas', '')
        this._canvas_label = L.DomUtil.create('canvas', '')
        this._canvas.style.pointerEvents = "none"
        this._canvas_label.style.pointerEvents = "none"
        this._setZindex(this.options.zIndex)
        if (this._map.options.zoomAnimation && L.Browser.any3d) {
            L.DomUtil.addClass(this._canvas, 'leaflet-zoom-animated')
            L.DomUtil.addClass(this._canvas_label, 'leaflet-zoom-animated')
        } else {
            L.DomUtil.addClass(this._canvas, 'leaflet-zoom-hide')
            L.DomUtil.addClass(this._canvas_label, 'leaflet-zoom-animated')
        }
        this._container.appendChild(this._canvas)
        this._container.appendChild(this._canvas_label)
        L.extend(this._canvas, {
            onselectstart: L.Util.falseFn,
            onmousemove: L.Util.falseFn,
            onload: L.bind(this._onCanvasLoad, this)
        })
        L.extend(this._canvas_label, {
            onselectstart: L.Util.falseFn,
            onmousemove: L.Util.falseFn,
            onload: L.bind(this._onCanvasLoad, this)
        })
    },
    _animateZoom: function (e) {
        let map = this._map,
            container = this._container,
            canvas = this._canvas,
            scale = map.getZoomScale(e.zoom),
            nw = map.containerPointToLatLng([0, 0]),
            se = map.containerPointToLatLng([canvas.width, canvas.height]),
            topLeft = map._latLngToNewLayerPoint(nw, e.zoom, e.center),
            size = map._latLngToNewLayerPoint(se, e.zoom, e.center)._subtract(topLeft),
            origin = topLeft._add(size._multiplyBy((1 / 2) * (1 - 1 / scale)))
    },
    _onCanvasLoad: function () {
        this.fire('load')
    },
    setData: function (data) {
        let self = this
        self.allData = data
        self._reset()
    },
    _reset: function () {
        if (this.options.allowDraw) {
            let self = this
            let container = this._container, canvas = this._canvas
            if (!this._map) { return }
            let size = this._map.getSize(), lt = this._map.containerPointToLayerPoint([0, 0])
            L.DomUtil.setPosition(container, lt)
            this.width = size.x
            this.height = size.y
            container.style.width = size.x + 'px'
            container.style.height = size.y + 'px'
            canvas.style.width = size.x + 'px'
            canvas.style.height = size.y + 'px'
            canvas.width = size.x * self.options.scale
            canvas.height = size.y * self.options.scale
            let d = self.allData.map(el => {
                let r = self.calRadius(el.center, el.radius)
                let r2 = { ...el }
                r2.center = r.center
                r2.radius = r.radius
                return r2
            })
            self._draw(d)
        }
    },
    calRadius: function (center, radius) {
        let self = this, map = self._map
        let centerContainer = map.latLngToContainerPoint(center)
        let rArray = []
        for (let index = 0; index < radius.length; index++) {
            let a1 = L.latLng((center[0] + radius[index] / 111.24), center[1])
            let b1 = map.latLngToContainerPoint(a1)
            let r1 = self._distan(centerContainer.x, centerContainer.y, b1.x, b1.y)
            rArray.push(r1 * self.options.scale)
        }
        return {
            center: centerContainer,
            radius: rArray,
        }
    },
    _distan: function (x1, y1, x2, y2) {
        let a1 = Math.pow(x1 - x2, 2)
        let a2 = Math.pow(y1 - y2, 2)
        return Math.sqrt(a1 + a2)
    },
    _draw: function (param) {
        let self = this, canvas = self._canvas, map = self._map
        if (L.Browser.canvas && map) {
            let Cwidth = canvas.clientWidth
            let Cheight = canvas.clientHeight
            let ctx = canvas.getContext("2d")
            ctx.clearRect(0, 0, Cwidth, Cheight)
            ctx.lineWidth = self.options.lineWidth
            for (let index = 0; index < param.length; index++) {
                let center = param[index].center
                let radius = param[index].radius
                let strokeStyle = param[index].strokeStyle
                let fillStyle = param[index].fillStyle
                center.x = center.x * self.options.scale
                center.y = center.y * self.options.scale
                ctx.strokeStyle = strokeStyle
                let startAngle = 0 //开始
                let endAngle = 0 //结束
                //先描边
                ctx.beginPath()
                ctx.moveTo(center.x + radius[0], center.y)
                for (let i = 0; i < radius.length; i++) {
                    endAngle = endAngle + 0.25 * Math.PI * 2
                    ctx.arc(center.x, center.y, radius[i], startAngle, endAngle, false)
                    startAngle = endAngle
                }
                ctx.closePath()
                ctx.stroke()
                //后填充
                endAngle = 0
                for (let i = 0; i < radius.length; i++) {
                    endAngle = endAngle + 0.25 * Math.PI * 2
                    ctx.beginPath()
                    ctx.moveTo(center.x, center.y)
                    ctx.arc(center.x, center.y, radius[i], startAngle, endAngle, false)
                    ctx.closePath()
                    ctx.fillStyle = fillStyle
                    ctx.fill()
                    startAngle = endAngle
                }
            }
        }
    },
    _clearcanvas: function () {
        let self = this, canvas = self._canvas, map = self._map
        if (L.Browser.canvas && map) {
            let Cwidth = canvas.clientWidth
            let Cheight = canvas.clientHeight
            let ctx = canvas.getContext("2d")
            ctx.clearRect(0, 0, Cwidth * self.options.scale, Cheight * self.options.scale)
        }
    }
})

export default function (options) {
    return new L.tycircleLayer(options)
}